package com.tca.common.compress.impl;

import cn.hutool.core.io.FileUtil;
import com.tca.common.compress.exception.CompressException;
import com.tca.common.core.bean.Result;
import com.tca.common.core.utils.ValidateUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;



/**
 * @author zhouan
 * @Date 2021/9/11
 */
@Slf4j
public class RarAdapter implements ICompressAdapter {

    @Override
    public boolean supports(String fileName) {
        if (ValidateUtils.isEmpty(fileName)) {
            return false;
        }
        return fileName.toLowerCase().endsWith("rar");
    }

    @Override
    public Result<String> uncompress(String fileName, String dir) {
        // 1.源rar文件
        File file = new File(fileName);
        // 2.解压后的文件路径
        File unrarDir = ValidateUtils.isEmpty(dir)?
                new File(file.getParentFile().getAbsolutePath()):
                new File(dir);
        if (!unrarDir.exists() || !unrarDir.isDirectory()) {
            unrarDir.mkdirs();
        }
        // 3.开始解压
        // rar5源文件
        RandomAccessFile randomAccessFile = null;
        IInArchive inArchive = null;
        try {
            randomAccessFile = new RandomAccessFile(file.getAbsolutePath(), "r");
            // autodetect archive type
            inArchive = SevenZip.openInArchive(null,
                    new RandomAccessFileInStream(randomAccessFile));

            // Getting simple interface of the archive inArchive
            ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();

            for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
                if (!item.isFolder()) {
                    ExtractOperationResult result;

                    result = item.extractSlow(data -> {
                        String outPath = new File(unrarDir, item.getPath()).getAbsolutePath();
                        File parentFile = new File(outPath).getParentFile();
                        if (!parentFile.exists() || !parentFile.isDirectory()) {
                            parentFile.mkdirs();
                        }
                        // 解压
                        try {
                            // 这里使用追加写
                            FileUtil.writeBytes(data, new File(outPath), 0, data.length, true);
                        } catch (Exception e) {
                            log.error("解压失败", e);
                            throw new CompressException("解压失败", e);
                        }
                        return data.length;
                    });
                    if (result != ExtractOperationResult.OK) {
                        return Result.failure("解压失败");
                    }
                }
            }
        } catch (Exception e) {
            log.error("解压失败", e);
            return Result.failure("解压失败");
        } finally {
            if (inArchive != null) {
                try {
                    inArchive.close();
                } catch (SevenZipException e) {
                    log.error("文件流关闭失败", e);
                }
            }
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    log.error("文件流关闭失败", e);
                }
            }
        }


        return Result.success(unrarDir.getAbsolutePath());
    }

    @Override
    public Result<String> uncompress(String fileName) {
        return uncompress(fileName, null);
    }


}
